﻿

using DualPlaneFR4Paster.Common.Services;
using DualPlaneFR4Paster.Extensions;
using DualPlaneFR4Paster.Models;
using HalconDotNet;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Query.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using Newtonsoft.Json;
using NLog;
using Prism.Commands;
using Prism.Ioc;
using Prism.Regions.Behaviors;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using ViewROI;

namespace DualPlaneFR4Paster.ViewModels.Dialogs.Camera
{
    public class CameraFilmVisionCalcDialogViewModel : DialogViewModel
    {
        #region 变量
        private readonly IContainerProvider _containerProvider;
        private static Logger logger = LogManager.GetCurrentClassLogger();
        private int floor = 1;
        private string partNum = string.Empty;
        private ICameraService cam1;
        CancellationTokenSource source;
        List<HObject> hImages;
        private IGTSCardService Top_A4;
        private IGTSCardService Top_A8;
        private IGTSCardService Bottom_A8;
        double xjogspeed = 0;
        double yjogspeed = 0;
        double zjogspeed = 0;
        double rjogspeed = 0;
        double z1safe = 0;
        double z2safe = 0;
        double z3safe = 0;
        double z4safe = 0;
        double cameraGrabPreTime = 0;
        #endregion
        #region 属性绑定
        #region halcon
        #region 1#
        private HImage cameraIamge0;
        public HImage CameraIamge0
        {
            get { return cameraIamge0; }
            set { SetProperty(ref cameraIamge0, value); }
        }
        private bool cameraRepaint0;
        public bool CameraRepaint0
        {
            get { return cameraRepaint0; }
            set { SetProperty(ref cameraRepaint0, value); }
        }
        private ObservableCollection<ROI> cameraROIList0 = new ObservableCollection<ROI>();
        public ObservableCollection<ROI> CameraROIList0
        {
            get { return cameraROIList0; }
            set { SetProperty(ref cameraROIList0, value); }
        }
        private HObject cameraAppendHObject0;
        public HObject CameraAppendHObject0
        {
            get { return cameraAppendHObject0; }
            set { SetProperty(ref cameraAppendHObject0, value); }
        }
        private HMsgEntry cameraAppendHMessage0;
        public HMsgEntry CameraAppendHMessage0
        {
            get { return cameraAppendHMessage0; }
            set { SetProperty(ref cameraAppendHMessage0, value); }
        }
        private Tuple<string, object> cameraGCStyle0;
        public Tuple<string, object> CameraGCStyle0
        {
            get { return cameraGCStyle0; }
            set { SetProperty(ref cameraGCStyle0, value); }
        }
        #endregion
        #endregion
        private int suckerSelectedIndex;
        public int SuckerSelectedIndex
        {
            get { return suckerSelectedIndex; }
            set { SetProperty(ref suckerSelectedIndex, value); }
        }
        private bool isBusy;
        public bool IsBusy
        {
            get { return isBusy; }
            set { SetProperty(ref isBusy, value); }
        }
        private bool isFlyGrabComboBoxVisible;
        public bool IsFlyGrabComboBoxVisible
        {
            get { return isFlyGrabComboBoxVisible; }
            set { SetProperty(ref isFlyGrabComboBoxVisible, value); }
        }
        private bool liveToggleButtonIsChecked;
        public bool LiveToggleButtonIsChecked
        {
            get { return liveToggleButtonIsChecked; }
            set { SetProperty(ref liveToggleButtonIsChecked, value); }
        }
        private ObservableCollection<AxisPointDisp> pointList1;
        public ObservableCollection<AxisPointDisp> PointList1
        {
            get { return pointList1; }
            set { SetProperty(ref pointList1, value); }
        }
        #endregion
        #region 方法绑定
        private DelegateCommand<object> cameraOperateCommand;
        public DelegateCommand<object> CameraOperateCommand =>
            cameraOperateCommand ?? (cameraOperateCommand = new DelegateCommand<object>(ExecuteCameraOperateCommand));
        private DelegateCommand<object> liveGrabCommand;
        public DelegateCommand<object> LiveGrabCommand =>
            liveGrabCommand ?? (liveGrabCommand = new DelegateCommand<object>(ExecuteLiveGrabCommand));
        private DelegateCommand<object> suckerIndexSelectCommand;
        public DelegateCommand<object> SuckerIndexSelectCommand =>
            suckerIndexSelectCommand ?? (suckerIndexSelectCommand = new DelegateCommand<object>(ExecuteSuckerIndexSelectCommand));
        private DelegateCommand<object> comboBoxSelectionChangedCommand;
        public DelegateCommand<object> ComboBoxSelectionChangedCommand =>
            comboBoxSelectionChangedCommand ?? (comboBoxSelectionChangedCommand = new DelegateCommand<object>(ExecuteComboBoxSelectionChangedCommand));
        private DelegateCommand flyGrabOperateCommand;
        public DelegateCommand FlyGrabOperateCommand =>
            flyGrabOperateCommand ?? (flyGrabOperateCommand = new DelegateCommand(ExecuteFlyGrabOperateCommand));
        private DelegateCommand<AxisPointDisp> pointList1JumpPosCommand;
        public DelegateCommand<AxisPointDisp> PointList1JumpPosCommand =>
            pointList1JumpPosCommand ?? (pointList1JumpPosCommand = new DelegateCommand<AxisPointDisp>(ExecutePointList1JumpPosCommand));
        private DelegateCommand createRecognizeRegionCommand;
        public DelegateCommand CreateRecognizeRegionCommand =>
            createRecognizeRegionCommand ?? (createRecognizeRegionCommand = new DelegateCommand(ExecuteCreateRecognizeRegionCommand));
        private DelegateCommand createShapeModelCommand;
        public DelegateCommand CreateShapeModelCommand =>
            createShapeModelCommand ?? (createShapeModelCommand = new DelegateCommand(ExecuteCreateShapeModelCommand));
        private DelegateCommand findShapeModelCommand;
        public DelegateCommand FindShapeModelCommand =>
            findShapeModelCommand ?? (findShapeModelCommand = new DelegateCommand(ExecuteFindShapeModelCommand));
        private DelegateCommand<string> createLineCommand;
        public DelegateCommand<string> CreateLineCommand =>
            createLineCommand ?? (createLineCommand = new DelegateCommand<string>(ExecuteCreateLineCommand));
        private DelegateCommand calculateCommand;
        public DelegateCommand CalculateCommand =>
            calculateCommand ?? (calculateCommand = new DelegateCommand(ExecuteCalculateCommand));

        void ExecuteCalculateCommand()
        {
            try
            {
                string filepath = $"{partNum}\\Camera\\{(floor == 1 ? "Top" : "Bottom")}\\Calc\\Down\\{SuckerSelectedIndex + 1}";
                string standardfilepath = $"{partNum}\\Camera\\{(floor == 1 ? "Top" : "Bottom")}\\Calc\\Down\\Standard";
                string calibfilepath = $"Camera\\{(floor == 1 ? "Top" : "Bottom")}\\Calib\\Down";
                HOperatorSet.ReadRegion(out var recognizeRegion, System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, $"RecognizeRegion.hobj"));
                CameraAppendHObject0 = null;
                CameraGCStyle0 = new Tuple<string, object>("Color", "yellow");
                CameraGCStyle0 = new Tuple<string, object>("DrawMode", "margin");
                CameraAppendHObject0 = recognizeRegion;
                HTuple ModelID;
                HOperatorSet.ReadShapeModel(System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, $"ShapeModelID.shm"), out ModelID);
                HObject imageReduced;
                HOperatorSet.ReduceDomain(CameraIamge0, recognizeRegion, out imageReduced);
                HTuple Row, Column, Angle, Score;
                HOperatorSet.FindShapeModel(imageReduced, ModelID, new HTuple(-180).TupleRad(), new HTuple(360).TupleRad(), 0.5, 1, 0.5, "least_squares", new HTuple(5).TupleConcat(1), 0.75, out Row, out Column, out Angle, out Score);
                HOperatorSet.ClearShapeModel(ModelID);
                HTuple HomMat2D;
                HOperatorSet.HomMat2dIdentity(out HomMat2D);
                HOperatorSet.HomMat2dRotate(HomMat2D, Angle, 0, 0, out HomMat2D);
                HOperatorSet.HomMat2dTranslate(HomMat2D, Row, Column, out HomMat2D);
                HTuple hv_DxfStatus; HObject ModelContours;
                HOperatorSet.ReadContourXldDxf(out ModelContours, System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, $"ShapeModelContours.dxf"), new HTuple(), new HTuple(), out hv_DxfStatus);
                HObject TransContours;
                HOperatorSet.AffineTransContourXld(ModelContours, out TransContours, HomMat2D);
                CameraGCStyle0 = new Tuple<string, object>("Color", "green");
                CameraGCStyle0 = new Tuple<string, object>("DrawMode", "margin");
                CameraAppendHObject0 = TransContours;
                HTuple ShapeModelRow, ShapeModelColumn, ShapeModelAngle;
                HOperatorSet.ReadTuple(System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, $"ShapeModelRow.tup"),out ShapeModelRow);
                HOperatorSet.ReadTuple(System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, $"ShapeModelColumn.tup"), out ShapeModelColumn);
                HOperatorSet.ReadTuple(System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, $"ShapeModelAngle.tup"), out ShapeModelAngle);
                HTuple ShapeHomMat2D;
                HOperatorSet.VectorAngleToRigid(ShapeModelRow, ShapeModelColumn, ShapeModelAngle, Row, Column, Angle, out ShapeHomMat2D);

                string jsonString = File.ReadAllText(System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath,"LineRegion1.json"));
                ROILine roiLine1 = JsonConvert.DeserializeObject<ROILine>(jsonString);

                HTuple _qx1, _qy1, _qx2, _qy2;
                HOperatorSet.AffineTransPoint2d(ShapeHomMat2D, roiLine1.row1, roiLine1.col1, out _qx1, out _qy1);
                HOperatorSet.AffineTransPoint2d(ShapeHomMat2D, roiLine1.row2, roiLine1.col2, out _qx2, out _qy2);

                ImageCalc.MFindLine(CameraIamge0, out var roiLine1Region, _qx1, _qy1, _qx2, _qy2, 20, 30, 0.6, out var line1Row1, out var line1Column1, out var line1Row2, out var line1Column2, out var resultLine);
                CameraGCStyle0 = new Tuple<string, object>("Color", "cyan");
                CameraGCStyle0 = new Tuple<string, object>("DrawMode", "fill");
                CameraAppendHObject0 = roiLine1Region;

                jsonString = File.ReadAllText(System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, "LineRegion2.json"));
                ROILine roiLine2 = JsonConvert.DeserializeObject<ROILine>(jsonString);
                HOperatorSet.AffineTransPoint2d(ShapeHomMat2D, roiLine2.row1, roiLine2.col1, out _qx1, out _qy1);
                HOperatorSet.AffineTransPoint2d(ShapeHomMat2D, roiLine2.row2, roiLine2.col2, out _qx2, out _qy2);

                ImageCalc.MFindLine(CameraIamge0, out var roiLine2Region, _qx1, _qy1, _qx2, _qy2, 20, 30, 0.6, out var line2Row1, out var line2Column1, out var line2Row2, out var line2Column2, out resultLine);
                CameraAppendHObject0 = roiLine2Region;

                HTuple intersectionRow, intersectionColumn, isOverlapping;
                HOperatorSet.IntersectionLines(line1Row1, line1Column1, line1Row2, line1Column2, line2Row1, line2Column1, line2Row2, line2Column2, out intersectionRow, out intersectionColumn, out isOverlapping);

                HTuple hv_Angle;
                HOperatorSet.AngleLx(line1Row1, line1Column1, line1Row2, line1Column2, out hv_Angle);
                HOperatorSet.SetColor(Global.CameraImageViewer.HWindowHalconID, "red");
                HOperatorSet.DispCross(Global.CameraImageViewer.HWindowHalconID, intersectionRow, intersectionColumn, 10, hv_Angle);
                CameraAppendHMessage0 = null;
                CameraAppendHMessage0 = new HMsgEntry($"坐标:{intersectionRow.D:F1},{intersectionColumn.D:F1},{hv_Angle.TupleDeg().D:F1}°", 100, 100);
                var result = _dialogHostService.MessageBox(MessageType.Confirm, "信息", $"计算成功!\n设置为\"吸头{SuckerSelectedIndex + 1}\"的基准位置吗？");
                if (result == ButtonResult.Yes)
                {
                    HOperatorSet.WriteTuple(intersectionRow, System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, "StandardRow.tup"));
                    HOperatorSet.WriteTuple(intersectionColumn, System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, "StandardColumn.tup"));
                    HOperatorSet.WriteTuple(hv_Angle, System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, "StandardAngle.tup"));
                    HOperatorSet.WriteImage(CameraIamge0, "jpeg", 0, System.IO.Path.Combine(System.Environment.CurrentDirectory, standardfilepath, $"{SuckerSelectedIndex + 1}.jpg"));
                }
                HTuple StandardRow, StandardColumn, StandardAngle;
                HOperatorSet.ReadTuple(System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, "StandardRow.tup"), out StandardRow);
                HOperatorSet.ReadTuple(System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, "StandardColumn.tup"), out StandardColumn);
                HOperatorSet.ReadTuple(System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, "StandardAngle.tup"), out StandardAngle);
                HTuple CalibHomMat2D;
                HOperatorSet.ReadTuple(System.IO.Path.Combine(System.Environment.CurrentDirectory, calibfilepath, "CalibHomMat2D.tup"), out CalibHomMat2D);
                HTuple standardx, standardy;
                HOperatorSet.AffineTransPoint2d(CalibHomMat2D, StandardRow, StandardColumn, out standardx, out standardy);
                HTuple newx, newy;
                HOperatorSet.AffineTransPoint2d(CalibHomMat2D, intersectionRow, intersectionColumn, out newx, out newy);

                HTuple homMat2D;
                HOperatorSet.VectorAngleToRigid(newx, newy, hv_Angle * -1, standardx , standardy, StandardAngle * -1, out homMat2D);//相机里的角度和实际的角度是反向的
                var point1 = PointList1.FirstOrDefault(p => p.Name == "ButtomCameraGrab_Sucker1");
                double grabx = point1.X, graby = point1.Y;
                switch (SuckerSelectedIndex)
                {
                    case 1:
                    case 2:
                    case 3:
                        {
                            var _centerpoint = PointList1.FirstOrDefault(p => p.Name == $"CenterSuck{SuckerSelectedIndex + 1}");
                            graby = point1.Y + _centerpoint.Y;                            
                        }
                        break;
                }
                HOperatorSet.VectorAngleToRigid(newx, newy, hv_Angle * -1, standardx, standardy, StandardAngle * -1, out homMat2D);
                HTuple calcX, calcY;
                HOperatorSet.AffineTransPoint2d(homMat2D, grabx, graby, out calcX, out calcY);
                double deltax = calcX.D - grabx;
                double deltay = calcY.D - graby;
                HTuple deltaangle = StandardAngle * -1 - hv_Angle * -1;
                if (deltaangle > Math.PI)
                {
                    deltaangle -= 2 * Math.PI;
                }
                if (deltaangle < Math.PI * -1)
                {
                    deltaangle += 2 * Math.PI;
                }
                CameraAppendHMessage0 = new HMsgEntry($"计算结果 ΔX={deltax:F2}, ΔY={deltay:F1},ΔR={deltaangle.TupleDeg().D:F2}°", 300, 100);
            }
            catch (Exception ex)
            {
                _dialogHostService.MessageBox(MessageType.Message, "信息", ex.Message);
            }
        }
        void ExecuteCreateLineCommand(string obj)
        {
            int lineIndex = int.Parse(obj);
            var result = _dialogHostService.MessageBox(MessageType.Confirm, "信息", $"确定重新画\"吸头{SuckerSelectedIndex + 1}\"的直线{lineIndex + 1}吗？");
            if (result == ButtonResult.Yes)
            {
                string filepath = $"{partNum}\\Camera\\{(floor == 1 ? "Top" : "Bottom")}\\Calc\\Down\\{SuckerSelectedIndex + 1}";
                try
                {
                    ROI roi = Global.CameraImageViewer.DrawROI(ROI.ROI_TYPE_LINE);
                    string jsonString = JsonConvert.SerializeObject(roi, Newtonsoft.Json.Formatting.Indented);
                    File.WriteAllText(System.IO.Path.Combine(System.Environment.CurrentDirectory,filepath,$"LineRegion{lineIndex + 1}.json"), jsonString);
                    var region = roi.getRegion();
                    CameraAppendHObject0 = null;
                    CameraGCStyle0 = new Tuple<string, object>("Color", "magenta");
                    CameraGCStyle0 = new Tuple<string, object>("DrawMode", "margin");
                    CameraAppendHObject0 = region;
                }
                catch (Exception ex)
                {
                    _dialogHostService.MessageBox(MessageType.Message, "信息", ex.Message);
                }
            }
        }
        void ExecuteFindShapeModelCommand()
        {
            try
            {
                string filepath = $"{partNum}\\Camera\\{(floor == 1 ? "Top" : "Bottom")}\\Calc\\Down\\{SuckerSelectedIndex + 1}";
                HObject recognizeRegion;
                HOperatorSet.ReadRegion(out recognizeRegion, System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, $"RecognizeRegion.hobj"));
                CameraAppendHObject0 = null;
                CameraGCStyle0 = new Tuple<string, object>("Color", "yellow");
                CameraGCStyle0 = new Tuple<string, object>("DrawMode", "margin");
                CameraAppendHObject0 = recognizeRegion;
                HTuple ModelID;
                HOperatorSet.ReadShapeModel(System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, $"ShapeModelID.shm"), out ModelID);
                HObject imageReduced;
                HOperatorSet.ReduceDomain(CameraIamge0, recognizeRegion,out imageReduced);
                HTuple Row, Column, Angle, Score;
                HOperatorSet.FindShapeModel(imageReduced, ModelID, new HTuple(-180).TupleRad(), new HTuple(360).TupleRad(), 0.5, 1, 0.5, "least_squares", new HTuple(5).TupleConcat(1), 0.75, out Row, out Column, out Angle, out Score);
                HOperatorSet.ClearShapeModel(ModelID);
                HTuple HomMat2D;
                HOperatorSet.HomMat2dIdentity(out HomMat2D);
                HOperatorSet.HomMat2dRotate(HomMat2D, Angle, 0, 0, out HomMat2D);
                HOperatorSet.HomMat2dTranslate(HomMat2D, Row, Column, out HomMat2D);
                HTuple hv_DxfStatus; HObject ModelContours;
                HOperatorSet.ReadContourXldDxf(out ModelContours, System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, $"ShapeModelContours.dxf"), new HTuple(), new HTuple(), out hv_DxfStatus);
                HObject TransContours;
                HOperatorSet.AffineTransContourXld(ModelContours, out TransContours, HomMat2D);
                CameraGCStyle0 = new Tuple<string, object>("Color", "green");
                CameraGCStyle0 = new Tuple<string, object>("DrawMode", "margin");
                CameraAppendHObject0 = TransContours;
                CameraAppendHMessage0 = null;
                CameraAppendHMessage0 = new HMsgEntry($"坐标:{Row.D:F1},{Column.D:F1},{Angle.TupleDeg().D:F1}° 分数:{Score.D:F1}", 100, 100);
                var result = _dialogHostService.MessageBox(MessageType.Confirm, "信息", $"设置为\"吸头{SuckerSelectedIndex + 1}\"的基准模板位置吗？");
                if (result == ButtonResult.Yes)
                {
                    HOperatorSet.WriteTuple(Row, System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, $"ShapeModelRow.tup"));
                    HOperatorSet.WriteTuple(Column, System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, $"ShapeModelColumn.tup"));
                    HOperatorSet.WriteTuple(Angle, System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, $"ShapeModelAngle.tup"));
                    HOperatorSet.WriteImage(CameraIamge0, "jpeg", 0, System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, $"SampleImage.jpg"));
                }
            }
            catch (Exception ex)
            {
                _dialogHostService.MessageBox(MessageType.Message, "信息", ex.Message);
            }
        }
        void ExecuteCreateShapeModelCommand()
        {
            var result = _dialogHostService.MessageBox(MessageType.Confirm, "信息", $"确定重新画\"吸头{SuckerSelectedIndex + 1}\"的识别模板吗？");
            if (result == ButtonResult.Yes)
            {
                string filepath = $"{partNum}\\Camera\\{(floor == 1 ? "Top" : "Bottom")}\\Calc\\Down\\{SuckerSelectedIndex + 1}";
                try
                {
                    ROI roi = Global.CameraImageViewer.DrawROI(ROI.ROI_TYPE_REGION);
                    HRegion ModelRegion = roi.getRegion();
                    HObject TemplateImage;
                    HOperatorSet.ReduceDomain(CameraIamge0, ModelRegion, out TemplateImage);
                    HTuple ModelID;
                    HOperatorSet.CreateShapeModel(TemplateImage, 3, new HTuple(-180).TupleRad(), new HTuple(360).TupleRad(), new HTuple(1).TupleRad(), new HTuple("none").TupleConcat("no_pregeneration"), "use_polarity", new HTuple(30).TupleConcat(30).TupleConcat(0), 10, out ModelID);
                    HObject ModelContours;
                    HOperatorSet.GetShapeModelContours(out ModelContours, ModelID, 1);
                    HTuple ModelRegionArea, RefRow, RefColumn;
                    HOperatorSet.AreaCenter(ModelRegion, out ModelRegionArea, out RefRow, out RefColumn);
                    HTuple HomMat2D;
                    HOperatorSet.VectorAngleToRigid(0, 0, 0, RefRow, RefColumn, 0, out HomMat2D);
                    HObject TransContours;
                    HOperatorSet.AffineTransContourXld(ModelContours, out TransContours, HomMat2D);
                    CameraAppendHObject0 = null;
                    CameraGCStyle0 = new Tuple<string, object>("Color", "green");
                    CameraGCStyle0 = new Tuple<string, object>("DrawMode", "margin");
                    CameraAppendHObject0 = TransContours;
                    CameraAppendHMessage0 = null;
                    CameraAppendHMessage0 = new HMsgEntry($"坐标:{RefRow.D:F1},{RefColumn.D:F1}", 100, 100);
                    HOperatorSet.WriteShapeModel(ModelID, System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, $"ShapeModelID.shm"));
                    HOperatorSet.ClearShapeModel(ModelID);
                    HOperatorSet.WriteContourXldDxf(ModelContours, System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, $"ShapeModelContours.dxf"));
                }
                catch (Exception ex)
                {
                    _dialogHostService.MessageBox(MessageType.Message, "信息", ex.Message);
                }
            }
        }
        void ExecuteCreateRecognizeRegionCommand()
        {
            var result = _dialogHostService.MessageBox(MessageType.Confirm, "信息", $"确定重新画\"吸头{SuckerSelectedIndex + 1}\"的识别区域吗？");
            if (result == ButtonResult.Yes)
            {
                string filepath = $"{partNum}\\Camera\\{(floor == 1 ? "Top" : "Bottom")}\\Calc\\Down\\{SuckerSelectedIndex + 1}";
                try
                {
                    ROI roi = Global.CameraImageViewer.DrawROI(ROI.ROI_TYPE_RECTANGLE1);
                    HRegion ModelRegion = roi.getRegion();
                    CameraAppendHObject0 = null;
                    CameraGCStyle0 = new Tuple<string, object>("Color", "yellow");
                    CameraGCStyle0 = new Tuple<string, object>("DrawMode", "margin");
                    CameraAppendHObject0 = ModelRegion;
                    HOperatorSet.WriteRegion(ModelRegion, System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, $"RecognizeRegion.hobj"));
                }
                catch (Exception ex)
                {
                    _dialogHostService.MessageBox(MessageType.Message, "信息", ex.Message);
                }
            }
        }
        void ExecutePointList1JumpPosCommand(AxisPointDisp point)
        {
            if (point != null)
            {
                var result = _dialogHostService.MessageBox(MessageType.Confirm, "信息", $"确认Jump运动到点\"{point.Alias}\"吗？");
                if (result == ButtonResult.Yes)
                {
                    AxisPointDisp point1;
                    if (point.Name == "CenterSuck2" || point.Name == "CenterSuck3" || point.Name == "CenterSuck4")
                    {
                        var _point = PointList1.FirstOrDefault(p => p.Name == "ButtomCameraGrab_Sucker1");
                        point1 = new AxisPointDisp
                        {
                            X = _point.X - point.X,
                            Y = _point.Y,
                            Z = _point.Z,
                            R = _point.R,
                            ZIndex = point.ZIndex,
                            RIndex = point.RIndex
                        };
                    }
                    else
                    {
                        point1 = point;
                    }
                    IsBusy = true;
                    source = new CancellationTokenSource();
                    CancellationToken token = source.Token;
                    Task.Run(() => JumpXYZRAction(token, point1), token).ContinueWith(t => { IsBusy = false; });
                }
            }
        }
        void ExecuteFlyGrabOperateCommand()
        {
            var result = _dialogHostService.MessageBox(MessageType.Confirm, "信息", "确认开始飞拍动作吗？");
            if (result == ButtonResult.Yes)
            {
                using (var db = new DTContext(partNum))
                {
                    var v1 = db.MParams.FirstOrDefault(p => p.Name == "XJogSpeed" && p.Floor == floor);
                    if (v1 != null)
                    {
                        xjogspeed = double.Parse(v1.Value);
                    }
                }
                if (LiveToggleButtonIsChecked)
                {
                    LiveToggleButtonIsChecked = false;
                    if (source != null)
                    {
                        source.Cancel();
                    }
                    System.Threading.Thread.Sleep(500);
                }
                IsBusy = true;
                hImages.Clear();
                cam1.ImageQueue.Clear();
                cam1.SetTriggerMode(1);
                cam1.StartGrabe();
                source = new CancellationTokenSource();
                CancellationToken token = source.Token;
                Task.Run(() => FlyGrabAction(token), token).ContinueWith(t => {
                    cam1.StopGrabe();
                    IsBusy = false;
                    IsFlyGrabComboBoxVisible = true;
                });
            }
        }
        void ExecuteComboBoxSelectionChangedCommand(object obj)
        {
            Debug.WriteLine(obj);
            CameraIamge0 = new HImage(hImages[(int)obj]);
        }
        void ExecuteSuckerIndexSelectCommand(object obj)
        {
            if (obj != null)
            {
                int index = int.Parse(obj.ToString());
                SuckerSelectedIndex = index;
                string filepath = $"{partNum}\\Camera\\{(floor == 1 ? "Top" : "Bottom")}\\Calc\\Down\\{index + 1}";
                string filename = System.IO.Path.Combine(System.Environment.CurrentDirectory, filepath, "SampleImage.jpg");
                if (File.Exists(filename))
                {
                    HObject image;
                    HOperatorSet.ReadImage(out image, filename);
                    CameraIamge0 = new HImage(image);
                }
            }
        }
        void ExecuteLiveGrabCommand(object isLiveGrab)
        {
            if ((bool)isLiveGrab)
            {
                source = new CancellationTokenSource();
                CancellationToken token = source.Token;
                Task.Run(() => ContinueGrab(token), token);
            }
            else
            {
                if (source != null)
                {
                    source.Cancel();
                }
            }
        }
        void ExecuteCameraOperateCommand(object obj)
        {
            switch (obj.ToString())
            {
                case "拍照":
                    {
                        if (LiveToggleButtonIsChecked)
                        {
                            LiveToggleButtonIsChecked = false;
                            if (source != null)
                            {
                                source.Cancel();
                            }
                            System.Threading.Thread.Sleep(500);
                        }
                        cam1.ImageQueue.Clear();
                        cam1.SetTriggerMode(0);
                        cam1.StartGrabe();
                        Task.Run(() => {
                            int mIndex = 0;
                            while (mIndex < 1)
                            {
                                HObject? hObj;
                                if (cam1.ImageQueue.TryPeek(out hObj))
                                {
                                    cam1.ImageQueue.TryDequeue(out hObj);
                                    CameraIamge0 = new HImage(hObj);
                                    mIndex++;
                                }
                            }
                        }).ContinueWith(t => { cam1.StopGrabe(); });
                    }
                    break;
                case "打开":
                    {
                        OpenFileDialog openFileDialog = new OpenFileDialog();
                        openFileDialog.Filter = "Image Files|*.png;*.bmp;*.jpg;*.tif";
                        if (openFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                        {
                            HObject image;
                            HOperatorSet.ReadImage(out image, openFileDialog.FileName);
                            CameraIamge0 = new HImage(image);
                        }
                    }
                    break;
                case "增强":
                    {
                        HObject imageScaled;
                        HTuple mult = 255.0 / (255 - 70);
                        HTuple add = -1 * mult * 70;
                        HOperatorSet.ScaleImage(CameraIamge0, out imageScaled, mult, add);
                        CameraIamge0 = new HImage(imageScaled);
                    }
                    break;
                default:
                    break;
            }
        }
        #endregion
        #region 导航
        public override void OnDialogOpened(IDialogParameters parameters)
        {
            floor = parameters.GetValue<int>("Floor");
            partNum = parameters.GetValue<string>("PartNum");
            Title = $"{(floor == 1 ? "上层" : "下层")}-{partNum}-拍膜相机 视觉算法";
            switch (floor)
            {
                case 1:
                    cam1 = _containerProvider.Resolve<ICameraService>("Floor1Down");
                    break;
                case 2:
                    cam1 = _containerProvider.Resolve<ICameraService>("Floor2Down");
                    break;
                default:
                    break;
            }
            
            using (var db = new DTContext(partNum))
            {
                var points = db.XYZRPoints.Where(p => (p.Name == "FlyStartPicker" || p.Name == "FlyEndPicker" || p.Name == "ButtomCameraGrab_Sucker1") && p.Floor == floor);
                if (points.Any())
                {
                    var posList = points.ToList();
                    foreach (var item in posList)
                    {
                        PointList1.Add(
                            new AxisPointDisp
                            {
                                Id = item.Id,
                                Name = item.Name,
                                Alias = item.Alias,
                                X = item.X,
                                Y = item.Y,
                                Z = item.Z,
                                R = item.R,
                                ZIndex = item.ZIndex,
                                RIndex = item.RIndex
                            }
                            );
                    }
                }
                var v1 = db.MParams.FirstOrDefault(p => p.Name == "XJogSpeed" && p.Floor == floor);
                if (v1 != null)
                {
                    xjogspeed = double.Parse(v1.Value);
                }
                v1 = db.MParams.FirstOrDefault(p => p.Name == "YJogSpeed" && p.Floor == floor);
                if (v1 != null)
                {
                    yjogspeed = double.Parse(v1.Value);
                }
                v1 = db.MParams.FirstOrDefault(p => p.Name == "ZJogSpeed" && p.Floor == floor);
                if (v1 != null)
                {
                    zjogspeed = double.Parse(v1.Value);
                }
                v1 = db.MParams.FirstOrDefault(p => p.Name == "RJogSpeed" && p.Floor == floor);
                if (v1 != null)
                {
                    rjogspeed = double.Parse(v1.Value);
                }
                v1 = db.MParams.FirstOrDefault(p => p.Name == "Z1SafePos" && p.Floor == floor);
                if (v1 != null)
                {
                    z1safe = double.Parse(v1.Value);
                }
                v1 = db.MParams.FirstOrDefault(p => p.Name == "Z2SafePos" && p.Floor == floor);
                if (v1 != null)
                {
                    z2safe = double.Parse(v1.Value);
                }
                v1 = db.MParams.FirstOrDefault(p => p.Name == "Z3SafePos" && p.Floor == floor);
                if (v1 != null)
                {
                    z3safe = double.Parse(v1.Value);
                }
                v1 = db.MParams.FirstOrDefault(p => p.Name == "Z4SafePos" && p.Floor == floor);
                if (v1 != null)
                {
                    z4safe = double.Parse(v1.Value);
                }
            }
            using (var sysDb = new SysContext())
            {
                var points = sysDb.XYZRPoints.Where(p => (p.Name.Contains("CenterSuck")) && p.Floor == floor);
                if (points.Any())
                {
                    var posList = points.ToList();
                    foreach (var item in posList)
                    {
                        PointList1.Add(
                            new AxisPointDisp
                            {
                                Id = item.Id,
                                Name = item.Name,
                                Alias = item.Alias,
                                X = item.X,
                                Y = item.Y,
                                Z = item.Z,
                                R = item.R,
                                ZIndex = item.ZIndex,
                                RIndex = item.RIndex
                            }
                            );
                    }
                }
                switch (floor)
                {
                    case 1:
                        {
                            var _param = sysDb.MSystemParams.FirstOrDefault(p => p.Name == "Floor1DownCameraGrabPreTime");
                            if (_param != null)
                            {
                                cameraGrabPreTime = double.Parse(_param.Value);
                            }
                        }
                        break;
                    case 2:
                        {
                            var _param = sysDb.MSystemParams.FirstOrDefault(p => p.Name == "Floor2DownCameraGrabPreTime");
                            if (_param != null)
                            {
                                cameraGrabPreTime = double.Parse(_param.Value);
                            }
                        }
                        break;
                    default:
                        break;
                }
            }
        }
        public override void OnDialogClosed()
        {
            cam1.StopGrabe();
            hImages.Clear();
            if (source != null)
            {
                source.Cancel();
            }
        }
        #endregion
        public CameraFilmVisionCalcDialogViewModel(IContainerProvider containerProvider) : base(containerProvider)
        {
            _containerProvider = containerProvider;
            SuckerSelectedIndex = 0;
            IsBusy = false;
            IsFlyGrabComboBoxVisible = false;
            LiveToggleButtonIsChecked = false;
            hImages = new List<HObject>();
            PointList1 = new ObservableCollection<AxisPointDisp>();
            Top_A4 = containerProvider.Resolve<IGTSCardService>("Top_A4");
            Top_A8 = containerProvider.Resolve<IGTSCardService>("Top_A8");
            Bottom_A8 = containerProvider.Resolve<IGTSCardService>("Bottom_A8");
        }
        #region 功能函数
        private void ContinueGrab(CancellationToken token)
        {
            cam1.ImageQueue.Clear();
            cam1.SetTriggerMode(0);
            cam1.StartGrabe();
            while (true)
            {
                if (token.IsCancellationRequested)
                {
                    cam1.StopGrabe();
                    return;
                }
                HObject? hObj;
                if (cam1.ImageQueue.TryPeek(out hObj))
                {
                    cam1.ImageQueue.TryDequeue(out hObj);
                    CameraIamge0 = new HImage(hObj);
                }
                System.Threading.Thread.Sleep(1);
            }
        }
        private void FlyGrabAction(CancellationToken token)
        {
            double flySpeed = xjogspeed > 1000 ? 1000 : xjogspeed;
            try
            {
                var axisX = floor == 1 ? Top_A8.A1 : Bottom_A8.A1;
                var axisY = floor == 1 ? Top_A8.A2 : Bottom_A8.A2;
                var axisZ1 = floor == 1 ? Top_A8.A4 : Bottom_A8.A4;
                var axisZ2 = floor == 1 ? Top_A8.A5 : Bottom_A8.A5;
                var axisZ3 = floor == 1 ? Top_A8.A6 : Bottom_A8.A6;
                var axisZ4 = floor == 1 ? Top_A8.A7 : Bottom_A8.A7;
                var axisR1 = floor == 1 ? Top_A4.A1 : Top_A4.A3;
                var axisR2 = floor == 1 ? Top_A4.A2 : Top_A4.A4;
                var _startPoint = PointList1.FirstOrDefault(p => p.Name == "FlyStartPicker");
                var _endPoint = PointList1.FirstOrDefault(p => p.Name == "FlyEndPicker");
                int stepnum = 0;
                while (true)
                {
                    if (token.IsCancellationRequested)
                    {
                        return;
                    }
                    switch (stepnum)
                    {
                        case 0://Z运动到安全位
                            {
                                GTSCard.AxisPosMove(ref axisZ1, z1safe, zjogspeed);
                                GTSCard.AxisPosMove(ref axisZ2, z2safe, zjogspeed);
                                GTSCard.AxisPosMove(ref axisZ3, z3safe, zjogspeed);
                                GTSCard.AxisPosMove(ref axisZ4, z4safe, zjogspeed);
                                stepnum = 1;
                            }
                            break;
                        case 1:
                            if (GTSCard.AxisPosMoveCheckDone(axisZ1) && GTSCard.AxisPosMoveCheckDone(axisZ2) && GTSCard.AxisPosMoveCheckDone(axisZ3) && GTSCard.AxisPosMoveCheckDone(axisZ4))
                            {
                                stepnum = 2;
                            }
                            break;
                        case 2:
                            {
                                GTSCard.AxisPosMove(ref axisX, _startPoint.X, xjogspeed);
                                GTSCard.AxisPosMove(ref axisY, _startPoint.Y, yjogspeed);
                                GTSCard.AxisPosMove(ref axisR1, _startPoint.R, rjogspeed);
                                GTSCard.AxisPosMove(ref axisR2, _startPoint.R, rjogspeed);
                                stepnum = 3;
                            }
                            break;
                        case 3:
                            if (GTSCard.AxisPosMoveCheckDone(axisX) && GTSCard.AxisPosMoveCheckDone(axisY) 
                                && GTSCard.AxisPosMoveCheckDone(axisR1) && GTSCard.AxisPosMoveCheckDone(axisR2))
                            {
                                stepnum = 4;
                            }
                            break;

                        case 4:
                            {
                                GTSCard.AxisPosMove(ref axisZ1, _startPoint.Z, zjogspeed);
                                GTSCard.AxisPosMove(ref axisZ2, _startPoint.Z, zjogspeed);
                                GTSCard.AxisPosMove(ref axisZ3, _startPoint.Z, zjogspeed);
                                GTSCard.AxisPosMove(ref axisZ4, _startPoint.Z, zjogspeed);
                                stepnum = 5;
                            }
                            break;
                        case 5:
                            if (GTSCard.AxisPosMoveCheckDone(axisZ1) && GTSCard.AxisPosMoveCheckDone(axisZ2) && GTSCard.AxisPosMoveCheckDone(axisZ3) && GTSCard.AxisPosMoveCheckDone(axisZ4))                                
                            {
                                stepnum = 6;
                            }
                            break;
                        case 6:
                            {
                                var _sucker1 = PointList1.FirstOrDefault(p => p.Name == "ButtomCameraGrab_Sucker1");
                                var _center2 = PointList1.FirstOrDefault(p => p.Name == "CenterSuck2");
                                var _center3 = PointList1.FirstOrDefault(p => p.Name == "CenterSuck3");
                                var _center4 = PointList1.FirstOrDefault(p => p.Name == "CenterSuck4");
                                int[] Buf1 = new int[4];
                                double dirfactor = _startPoint.X >= _endPoint.X ? -1 : 1;
                                double cameraGrabMovSpace = cameraGrabPreTime / 1000 * flySpeed;//相机拍照时间认为是0.4ms，此处算的是拍照过程的偏移距离
                                Buf1[0] = (int)((_sucker1.X - _startPoint.X - cameraGrabMovSpace * dirfactor) / axisX.Equiv);
                                Buf1[1] = Buf1[0] + (int)(_center2.X * dirfactor / axisX.Equiv);
                                Buf1[2] = Buf1[0] + (int)(_center3.X * dirfactor / axisX.Equiv);
                                Buf1[3] = Buf1[0] + (int)(_center4.X * dirfactor / axisX.Equiv);
                                GTSCard.AxisCompareUse2(axisX.CardNo, 1, Buf1);//设置飞拍数据
                                stepnum = 7;
                            }
                            break;
                        case 7:
                            {
                                GTSCard.AxisPosMove(ref axisX, _endPoint.X, flySpeed);
                                stepnum = 8;
                            }
                            break;
                        case 8:
                            if (GTSCard.AxisPosMoveCheckDone(axisX))
                            {
                                return;
                            }
                            else
                            {
                                while (cam1.ImageQueue.TryPeek(out var obj1))
                                {
                                    cam1.ImageQueue.TryDequeue(out var obj2);
                                    hImages.Add(obj2);
                                }
                            }
                            break;
                    }
                    System.Threading.Thread.Sleep(10);
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex);
                Debug.WriteLine(ex.Message);
            }
        }
        private void JumpXYZRAction(CancellationToken token, AxisPointDisp point)
        {
            try
            {
                var axisX = floor == 1 ? Top_A8.A1 : Bottom_A8.A1;
                var axisY = floor == 1 ? Top_A8.A2 : Bottom_A8.A2;
                var axisZ1 = floor == 1 ? Top_A8.A4 : Bottom_A8.A4;
                var axisZ2 = floor == 1 ? Top_A8.A5 : Bottom_A8.A5;
                var axisZ3 = floor == 1 ? Top_A8.A6 : Bottom_A8.A6;
                var axisZ4 = floor == 1 ? Top_A8.A7 : Bottom_A8.A7;
                AxisParm axisZ, axisR;
                switch (point.ZIndex)
                {
                    case 0:
                        axisZ = floor == 1 ? Top_A8.A4 : Bottom_A8.A4;
                        break;
                    case 1:
                        axisZ = floor == 1 ? Top_A8.A5 : Bottom_A8.A5;
                        break;
                    case 2:
                        axisZ = floor == 1 ? Top_A8.A6 : Bottom_A8.A6;
                        break;
                    case 3:
                    default:
                        axisZ = floor == 1 ? Top_A8.A7 : Bottom_A8.A7;
                        break;
                }
                switch (point.RIndex)
                {
                    case 0:
                        axisR = floor == 1 ? Top_A4.A1 : Top_A4.A3;
                        break;
                    case 1:
                    default:
                        axisR = floor == 1 ? Top_A4.A2 : Top_A4.A4;
                        break;
                }
                int stepnum = 0;
                while (true)
                {
                    if (token.IsCancellationRequested)
                    {
                        return;
                    }
                    switch (stepnum)
                    {
                        case 0://Z运动到安全位
                            {
                                GTSCard.AxisPosMove(ref axisZ1, z1safe, zjogspeed);
                                GTSCard.AxisPosMove(ref axisZ2, z2safe, zjogspeed);
                                GTSCard.AxisPosMove(ref axisZ3, z3safe, zjogspeed);
                                GTSCard.AxisPosMove(ref axisZ4, z4safe, zjogspeed);
                                stepnum = 1;
                            }
                            break;
                        case 1:
                            if (GTSCard.AxisPosMoveCheckDone(axisZ1) && GTSCard.AxisPosMoveCheckDone(axisZ2) && GTSCard.AxisPosMoveCheckDone(axisZ3) && GTSCard.AxisPosMoveCheckDone(axisZ4))
                            {
                                stepnum = 2;
                            }
                            break;
                        case 2:
                            {
                                GTSCard.AxisPosMove(ref axisX, point.X, xjogspeed);
                                GTSCard.AxisPosMove(ref axisY, point.Y, yjogspeed);
                                GTSCard.AxisPosMove(ref axisR, point.R, rjogspeed);
                                stepnum = 3;
                            }
                            break;
                        case 3:
                            if (GTSCard.AxisPosMoveCheckDone(axisX) && GTSCard.AxisPosMoveCheckDone(axisY) && GTSCard.AxisPosMoveCheckDone(axisR))
                            {
                                stepnum = 4;
                            }
                            break;
                        case 4:
                            {
                                GTSCard.AxisPosMove(ref axisZ, point.Z, zjogspeed);
                                stepnum = 5;
                            }
                            break;
                        case 5:
                            if (GTSCard.AxisPosMoveCheckDone(axisZ))
                            {
                                return;
                            }
                            break;
                        default:
                            break;
                    }
                    System.Threading.Thread.Sleep(100);
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex);
                Debug.WriteLine(ex.Message);
            }

        }
        #endregion
    }
}
